package edu.ynu.MyProject.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import edu.ynu.MyProject.common.service.LogicService;
import edu.ynu.MyProject.config.EquipmentConfig;
import edu.ynu.MyProject.dao.IDataDao;
import edu.ynu.MyProject.dto.DataDTO;
import edu.ynu.MyProject.dto.WeatherDTO;
import edu.ynu.MyProject.entity.Data;
import edu.ynu.MyProject.entity.GreenHouseInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.transaction.Transactional;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class DataService extends LogicService<IDataDao, Data, Long> {
    @Autowired
    private EquipmentService equipmentService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private GreenHouseService greenhouseService;
    @Autowired
    private RestTemplate restTemplate;

    public DataService(IDataDao iDataDao) {
        super(iDataDao);
    }

    @Transactional
    public String refreshData(Long greenhouseId) throws IOException {
        List<Data> allData = new ArrayList<>();
        try {
            // 调用设备服务获取设备数据
            ResponseEntity<List<Map<String, Object>>> response = equipmentService.getDeviceData(greenhouseId);

            // 如果响应体为空，跳过该 gid
            if (response.getBody() == null || response.getBody().isEmpty()) {
                // 记录该 gid 返回为空的数据
                System.out.println("No data returned for gid: " + greenhouseId);
            }

            // 获取响应体的内容，应该是 List<Map<String, Object>> 类型
            List<Map<String, Object>> deviceDataList = response.getBody();
            // 将 List<Map<String, Object>> 转换为 List<DeviceData>
            List<Data> DataResult = objectMapper.convertValue(deviceDataList,
                    objectMapper.getTypeFactory().constructCollectionType(List.class, Data.class));

            // 将该 gid 的设备数据添加到全部设备数据列表中
            allData.addAll(DataResult);
        } catch (Exception e) {
            // 记录该 gid 数据更新失败
            System.err.println("Error while processing greenhouseId: " + greenhouseId + " - " + e.getMessage());
        }


        // 将所有设备数据保存到数据库
        if (!allData.isEmpty()) {
            dao.saveAll(allData);
        } else {
            throw new IOException("No valid device data to save after processing all greenhouseIds.");
        }

        // 返回操作成功信息
        return "OK";
    }

    @Scheduled(cron = "0 0/30 * * * ?")//每三十分钟更新列表中全部大棚的所有数据
    @Transactional
    public String refreshDataAuto() throws IOException {
        List<GreenHouseInfo> greenhouses = greenhouseService.getAll();
        List<Data> allDeviceData = new ArrayList<>();

        for (GreenHouseInfo greenhouse : greenhouses) {
            Long gid = greenhouse.getId();
            try {
                // 调用设备服务获取设备数据
                ResponseEntity<List<Map<String, Object>>> response = equipmentService.getDeviceData(gid);
                // 如果响应体为空，跳过该 gid
                if (response.getBody() == null || response.getBody().isEmpty()) {
                    // 记录该 greenhouseId 返回为空的数据
                    System.out.println("No data returned for gid: " + gid);
                    continue;
                }
                // 获取响应体的内容，应该是 List<Map<String, Object>> 类型
                List<Map<String, Object>> deviceDataList = response.getBody();
                // 将 List<Map<String, Object>> 转换为 List<DeviceData>
                List<Data> deviceDataResult = objectMapper.convertValue(deviceDataList,
                        objectMapper.getTypeFactory().constructCollectionType(List.class, Data.class));
                // 将该 gid 的设备数据添加到全部设备数据列表中
                allDeviceData.addAll(deviceDataResult);
            } catch (Exception e) {
                // 记录该 gid 数据更新失败
                System.err.println("Error while processing gid: " + gid + " - " + e.getMessage());
            }
        }
        if (!allDeviceData.isEmpty()) {
            dao.saveAll(allDeviceData);
        } else {
            throw new IOException("No valid device data to save after processing all greenhouseIds auto.");
        }
        return " OK";
    }

    public Map<String, Object> getAllDataDTO(Long greenhouseId) throws IOException {

        List<Data> allDeviceData=dao.findLatestDataByGreenhouse(greenhouseId);
        List<DataDTO> allDeviceDataDto = allDeviceData.stream()
                .map(deviceData -> objectMapper.convertValue(deviceData, DataDTO.class))
                .collect(Collectors.toList());
        Map<String, Object> deviceDataMap = allDeviceDataDto.stream()
                .collect(Collectors.toMap(DataDTO::getName, DataDTO::getValue));

        // 返回转换后的 Map（Spring 会自动将其转为 JSON 格式）
        return deviceDataMap;
    }


    public String saveImages(Long greenhouseId) throws IOException {
        Map<String,Object> responseMap = equipmentService.getCameraCapture(greenhouseId);
        Map<String, Object> data = (Map<String, Object>) responseMap.get("data");
        String picUrl = (String) data.get("picUrl");
        byte[] imageBytes = downloadImage(picUrl);
        //将图片字节流保存到数据库
        Data data1 = new Data();
        data1.setImageData(imageBytes);
        data1.setDataType(18);
        data1.setEquipmentId(dao.findDeviceIdByGreenhouseIdAndType(greenhouseId));
        dao.save(data1);
        return "Image saved to database!";
    }
    public byte[] downloadImage(String picUrl) throws IOException {
        // 下载图片
        try {
            // 获取图片内容
            byte[] response = restTemplate.getForObject(URI.create(picUrl),byte[].class);
            // 获取响应的字节数组，即图片数据
            return response;
        } catch (Exception e) {
            // 捕获异常并抛出 IOException
            throw new IOException("Failed to download image from URL: " + picUrl, e);
        }
    }

    public WeatherDTO getTemperatureDTO(Long greenhouseId) throws IOException {
        WeatherDTO lineChartDto = new WeatherDTO();

        // 获取最近7天的日期
        List<String> dates = getLastSevenDaysDates();

        // 获取最近7天的土壤温度
        List<Double> soilTemperatures = getLastSevenDaysTemperature(greenhouseId,true);

        // 获取最近7天的空气温度
        List<Double> airTemperatures = getLastSevenDaysTemperature(greenhouseId,false);

        // 设置到 DTO 中
        lineChartDto.setDates(dates);
        lineChartDto.setSoilTemperatures(soilTemperatures);
        lineChartDto.setAirTemperatures(airTemperatures);

        return lineChartDto;
    }

    public List<Double> getLastSevenDaysTemperature(Long greenhouseId, boolean isSoilTemperature) {
        List<Double> temperatures = new ArrayList<>();
        LocalDate today = LocalDate.now();

        for (int i = 6; i >= 0; i--) {
            LocalDate date = today.minusDays(i); // 使用 LocalDate 获取前 i 天的日期
            Double average = null;
            String dateString = date.toString(); // 将日期转换为字符串

            try {
                if (isSoilTemperature) {
                    average = dao.findAverageSoilTemperatureByGreenhouseAndDate(greenhouseId, dateString);
                } else {
                    double airTemperature = dao.findAverageAirTemperatureByGreenhouseAndDate(greenhouseId, dateString);
                    average = airTemperature / 10; // 假设温度需要除以 10 进行单位转换
                }

                // 如果查询结果不为空，保留一位小数并添加到列表中
                if (average != null) {
                    BigDecimal roundedAverage = new BigDecimal(average).setScale(1, RoundingMode.HALF_UP);
                    temperatures.add(roundedAverage.doubleValue());
                } else {
                    temperatures.add(-1.0); // 如果没有数据，添加 -1.0 表示缺失数据
                }
            } catch (Exception e) {
                // 处理异常并输出错误信息
                System.err.println("Error fetching temperature for date: " + dateString);
                temperatures.add(-1.0); // 如果发生异常，返回 -1.0 表示缺失数据
            }
        }

        return temperatures;
    }

    public List<String> getLastSevenDaysDates() {
        List<String> dates = new ArrayList<>();
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");

        // 获取最近7天的日期
        for (int daysAgo = 6; daysAgo >= 0; daysAgo--) {
            LocalDate date = today.minusDays(daysAgo);
            dates.add(date.format(formatter)); // 格式化为字符串
        }
        return dates;
    }
    public File getImage(Long greenhouseId)  {
        byte[] img = dao.findLatestImagesByDataTypeAndGreenhouseId(greenhouseId);
        return changeImages(img);
    }

    public File changeImages(byte[] imageBytes) {
        try {
            File file = new File("C:/Users/GJH12/Desktop/image.png");
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fos.write(imageBytes);
                System.out.println("Image saved successfully: " + file.getAbsolutePath());
            }
            return file;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
